#pragma once
#include <iostream>
#include <cstring>
#include <string>
#include <cerrno>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <signal.h>
#include <sys/wait.h>

#include "Common.hpp"
#include "Log.hpp"
using namespace LogModule;
const uint16_t gport = 8080;
const int BACKLOG = 8;
class Server
{
public:
    Server(uint16_t port = gport)
        : _port(port), _isrunning(false)
    {
    }
    void Init()
    {
        // 创建TCP套接字               //面向字节流
        _listensockfd = socket(AF_INET, SOCK_STREAM, 0);
        if (_listensockfd < 0)
        {
            LOG(Loglevel::FATAL) << "socket filed";
            Die(SOCKET_ERROR);
        }
        LOG(Loglevel::INFO) << "socket success,sockfd:" << _listensockfd;
        // 填充网络信息
        struct sockaddr_in local;
        memset(&local, 0, sizeof(local));
        local.sin_family = AF_INET;
        local.sin_port = htons(_port);
        // 云服务器不允许绑定IP,所以要填任意IP
        local.sin_addr.s_addr = INADDR_ANY;
        int n = bind(_listensockfd, CONV(&local), sizeof(local));
        if (n < 0)
        {
            LOG(Loglevel::FATAL) << "bind filed";
            Die(BIND_ERROR);
        }
        LOG(Loglevel::INFO) << "bind success,sockfd:" << _listensockfd;
        // TCP是面向连接的,需要TCP随时随地等待被连接
        // 要将_listensockid设为监听状态
        n = listen(_listensockfd, BACKLOG); // 排队数,一般为4,8,16,32
        if (n < 0)
        {
            LOG(Loglevel::FATAL) << "listen filed";
            Die(LISTEN_ERROR);
        }
        LOG(Loglevel::INFO) << "listen success,sockfd:" << _listensockfd;

        // V1版本信号捕捉版本,子进程发送信号后就会自动释放
        // signal(SIGCHLD, SIG_IGN);
    }
    void Start()
    {
        _isrunning = true;
        while (_isrunning)
        {
            // TCP不能直接进行通信,要先建立连接
            sockaddr_in peer;
            socklen_t len = sizeof(peer);
            int sockfd = accept(_listensockfd, CONV(&peer), &len);
            if (sockfd < 0)
            {
                LOG(Loglevel::ERROR) << "accept filed" << strerror(errno);
            }
            LOG(Loglevel::INFO) << "accept success,sockfd:" << sockfd;
            // 单进程V1版本
            // HandlerRequest(sockfd);
            // 多进程V2版本
            int pid = fork();
            // 子进程继承父进程的文件描述符表,父子各一张
            // 父子各关闭自己不需要的文件描述符,就相当于父亲将自己的fd节点给子进程,由子进程统一处理
            if (pid == 0)
            {
                close(_listensockfd);
                // HandlerRequest(sockfd);
                // exit(0); // 子进程一定要退出,不然就执行循环和客户端建立连接了
                int id=fork();  //子进程再创建子进程来执行任务,创建完成后子进程直接退出
                if(id>0) exit(0);   //这样就不用父进程等待
                HandlerRequest(sockfd);  //此时孙子进程就成了孤儿进程,由OS进行管理
                exit(0);                 //退出后OS会进行资源释放          
            }
            close(sockfd);
            // 父进程不能一直等待子进程,因为父进程还要和其他客户端建立连接,此时可以使用信号捕捉处理
            // V1:信号捕捉
            // V2:孙子进程
            int rid=waitpid(pid,nullptr,0);
            if(rid<0)
            {
                LOG(Loglevel::WARING)<<"waitpid filed";
            }
        }
    }
    void HandlerRequest(int sockfd)
    {
        LOG(Loglevel::INFO) << "HandlerRequest,sockfd:" << sockfd;
        char inbuffer[1024];
        while (true)
        {
            int n = recv(sockfd, inbuffer, sizeof(inbuffer) - 1, 0);
            if (n > 0)
            {
                inbuffer[n] = 0; // 确保inbuffer以null结尾
                int n = send(sockfd, inbuffer, sizeof(inbuffer), 0);
                (void)n;
            }
        }
    }
    void Stop()
    {
        _isrunning = false;
    }
    ~Server()
    {
    }

private:
    int _listensockfd;
    uint16_t _port;
    bool _isrunning;
};